package com.ly.heart.service.king;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.erp.CommonUtil;
import com.ly.common.utils.erp.KingConstUtil;
import com.ly.heart.domain.KingOrgEntity;
import com.ly.heart.domain.KingSaleRefundDetailEntity;
import com.ly.heart.domain.KingSaleRefundEntity;
import com.ly.heart.domain.king.BaseChildBo;
import com.ly.heart.domain.king.saleRefund.SaleRefundBo;
import com.ly.heart.domain.king.saleRefund.SaleRefundDetailBo;
import com.ly.heart.domain.king.saleRefund.SaleRefundFinanceBo;
import com.ly.heart.domain.request.KingBaseSingleRequest;
import com.ly.heart.domain.response.KingBaseResponse;
import com.ly.heart.domain.response.KingBaseResponseError;
import com.ly.heart.domain.response.KingBaseResponseSuccessEntity;
import com.ly.heart.service.IKingOrgService;
import com.ly.heart.service.IKingSaleRefundDetailService;
import com.ly.heart.service.IKingSaleRefundService;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.heart.util.KingCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Component
@Slf4j
public class SaleRefundPushService {

    @Resource
    private IKingSaleRefundService iKingSaleRefundService;
    @Resource
    private IKingSaleRefundDetailService iKingSaleRefundDetailService;
    @Resource
    private IKingOrgService iKingOrgService;

    public void push ( String id ) {
        KingOrgEntity orgEntity = iKingOrgService.getOne ( new LambdaQueryWrapper<KingOrgEntity> ().eq ( KingOrgEntity :: getOrgId, CurrentUserUtil.getCompanyId () ).eq ( KingOrgEntity :: getIsDisabled, true ) );
        if ( orgEntity == null ) {
            throw new CustomException ( "请先至系统管理中配置金蝶账套！" );
        }
        IdentifyInfo identifyInfo = KingCommonUtil.getIdentifyInfo ( orgEntity );
        K3CloudApi client = new K3CloudApi ( identifyInfo );
        KingSaleRefundEntity saleRefundEntity = iKingSaleRefundService.getKingById ( id );
        if ( saleRefundEntity == null ) {
            throw new CustomException ( "无此单据" );
        }
        if ( saleRefundEntity.getIsSend () == KingConstUtil.KING_DATA_IS_SEND_YES ) {
            throw new CustomException ( "该单据已推金蝶，无需重复推送！" );
        }
        SaleRefundBo saleRefundBo = assembleSaleRefund ( saleRefundEntity );
        try {
            save ( saleRefundBo, client );
            submit ( saleRefundBo, client );
            audit ( saleRefundBo, client );
            updateSendSuccess ( id );
        } catch ( Exception e ) {
            e.printStackTrace ();
            throw new CustomException ( "推送失败，请检查后重试！" );
        }
    }


    private void save ( SaleRefundBo bo, K3CloudApi client ) throws Exception {
        KingBaseSingleRequest singleRequest = new KingBaseSingleRequest ();
        singleRequest.setModel ( bo );
        String s = JSONObject.toJSONString ( singleRequest );
        log.info ( "销售退货单转JSON->{}", s );
        String resultJson = client.save ( KingConstUtil.SAL_RETURNSTOCK, s );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "销售退货单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.info ( "{} 推送成功", sb );
        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "销售退货单-推送失败：【" + sb + "】" );
        }
    }

    private void submit ( SaleRefundBo bo, K3CloudApi client ) throws Exception {
        List<String> strings = new ArrayList<> ();
        strings.add ( bo.getFBillNo () );
        bo.setNumbers ( strings );
        String jsonData = JSON.toJSONString ( bo );
        String resultJson = client.submit ( KingConstUtil.SAL_RETURNSTOCK, jsonData );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            //提交成功
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "销售退货单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.error ( "{} 提交成功", sb );
        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "销售退货单提交失败：【" + sb + "】" );
        }
    }

    private void audit ( SaleRefundBo bo, K3CloudApi client ) throws Exception {
        List<String> strings = new ArrayList<> ();
        strings.add ( bo.getFBillNo () );
        bo.setNumbers ( strings );
        String jsonData = JSON.toJSONString ( bo );
        String resultJson = client.audit ( KingConstUtil.SAL_RETURNSTOCK, jsonData );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            //提交成功
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "销售退货单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.error ( "{} 审核成功", sb );
        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "销售退货单审核失败：【" + sb + "】" );
        }
    }

    private void updateSendSuccess ( String id ) {
        boolean update = iKingSaleRefundService.update ( new LambdaUpdateWrapper<KingSaleRefundEntity> ().set ( KingSaleRefundEntity :: getIsSend, KingConstUtil.KING_DATA_IS_SEND_YES ).eq ( KingSaleRefundEntity :: getId, id ) );
        if ( ! update ) {
            throw new CustomException ( "修改推送金蝶状态失败！" );
        }
    }

    private SaleRefundBo assembleSaleRefund ( KingSaleRefundEntity saleRefundEntity ) {
        SaleRefundBo bo = new SaleRefundBo ();
        //1.基
        bo.setFBillNo ( saleRefundEntity.getRefundCode () );
        //单据类型
        BaseChildBo billType = new BaseChildBo ().setFNumber ( saleRefundEntity.getDocType () );
        bo.setFBillTypeID ( billType );

        //销售组织必填项
        BaseChildBo FSaleOrgId = new BaseChildBo ().setFNumber ( /*saleRefundEntity.getSaleGroupCode ()*/ "100" );
        bo.setFSaleOrgId ( FSaleOrgId );

        //日期
        bo.setFDate ( CommonUtil.getDateStrFormat ( saleRefundEntity.getReturnGoodsDate (), "yyyy-MM-dd" ) );

        //库存组织
        BaseChildBo FStockOrgId = new BaseChildBo ().setFNumber ( /*saleRefundEntity.getInventoryGroupCode ()*/ "100" );
        bo.setFStockOrgId ( FStockOrgId );

        //退货客户
        BaseChildBo FRetcustId = new BaseChildBo ().setFNumber ( saleRefundEntity.getReturnCustomerCode () );
        bo.setFRetcustId ( FRetcustId );

        //财务模块：结算币别
        SaleRefundFinanceBo financeBo = new SaleRefundFinanceBo ();
        BaseChildBo FSettleCurrId = new BaseChildBo ().setFNumber ( saleRefundEntity.getSettlementCurrency () );
        financeBo.setFSettleCurrId ( FSettleCurrId );
        bo.setSubHeadEntity ( financeBo );

        //BaseChildBo FChageCondition = new BaseChildBo ().setFNumber ( saleRefundEntity.getpay () );
        //financeBo.setFChageCondition ( FChageCondition );

        List<SaleRefundDetailBo> saleRefundDetailBos = assembleSaleRefundDetail ( saleRefundEntity.getId () );
        bo.setFEntity ( saleRefundDetailBos );

        return bo;
    }

    private List<SaleRefundDetailBo> assembleSaleRefundDetail ( String saleRefundId ) {
        List<SaleRefundDetailBo> bos = new ArrayList<> ();
        List<KingSaleRefundDetailEntity> list = iKingSaleRefundDetailService.list ( new LambdaQueryWrapper<KingSaleRefundDetailEntity> ().
                eq ( KingSaleRefundDetailEntity :: getRelationId, saleRefundId ) );
        list.forEach ( detail -> {
            SaleRefundDetailBo bo = new SaleRefundDetailBo ();
            BaseChildBo FMaterialId = new BaseChildBo ().setFNumber ( detail.getMaterialCode () );
            bo.setFMaterialId ( FMaterialId );

            BaseChildBo FUnitID = new BaseChildBo ().setFNumber ( detail.getInventoryUnit () );
            bo.setFUnitID ( FUnitID );

            bo.setFMustqty ( detail.getShouldRefundNum () );
            bo.setFRealQty ( detail.getRefundNum () );

            BaseChildBo FStockId = new BaseChildBo ().setFNumber ( detail.getWarehouseCode () );
            bo.setFStockId ( FStockId );

            //bo.setFOwnerTypeId ( detail.getQualityType () );

            BaseChildBo FReturnType = new BaseChildBo ().setFNumber ( detail.getRefundType () );
            bo.setFReturnType ( FReturnType );

            bo.setFDeliveryDate ( CommonUtil.getDateStrFormat ( detail.getRefundDate (), "yyyy-MM-dd" ) );

            bos.add ( bo );
        } );
        return bos;
    }

}
